home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 5 / Apprentice-Release5.iso / Source Code / C / Frameworks / Grant's CGI Framework 1.0b14 / Util / FileUtil.c < prev    next >
Text File  |  1996-04-12  |  7KB  |  253 lines

  1. /*****
  2.  *
  3.  *    FileUtil.c
  4.  *
  5.  *    This is a support file for "Grant's CGI Framework".
  6.  *    Please see the license agreement that accompanies the distribution package
  7.  *    for licensing details.
  8.  *
  9.  *    Copyright ©1995,1996 by Grant Neufeld
  10.  *    grant@acm.com
  11.  *    http://arpp.carleton.ca/grant/mac/grantscgi/
  12.  *
  13.  *****/
  14.  
  15. #include "MyConfiguration.h"
  16.  
  17. #include <Aliases.h>
  18. #include <string.h>
  19.  
  20. #include "compiler_stuff.h"
  21.  
  22. #include "DebugUtil.h"
  23. #include "MemoryUtil.h"
  24.  
  25. #include "FileUtil.h"
  26.  
  27.  
  28. /***  LOCAL VARIABLES  ***/
  29.  
  30. /***  LOCAL CONSTANTS  ***/
  31.  
  32. /***  LOCAL PROTOTYPES  ***/
  33.  
  34. /***  FUNCTIONS  ***/
  35.  
  36. /* the data returned will not be null terminated */
  37. OSErr
  38. FileReadBytes ( short fileRef, long start, long lineLength, char *theLine, long *bytesRead )
  39. {
  40.     OSErr    theErr;
  41.     long    lineSize;
  42.     
  43.     my_assert ( fileRef != nil, "\pmyFileReadBytes: fileRef is nil" );
  44.     my_assert ( lineLength != nil, "\pmyFileReadBytes: lineLength is nil" );
  45.     my_assert ( theLine != NULL, "\pmyFileReadBytes: theLine ptr is NULL" );
  46.     my_assert ( bytesRead != NULL, "\pmyFileReadBytes: bytesRead ptr is NULL" );
  47.     
  48.     theErr = SetFPos ( fileRef, fsFromStart, start );
  49.     if ( theErr != noErr )
  50.     {
  51.         goto EXIT_FUNCTION;
  52.     }
  53.     
  54.     lineSize = lineLength - 1;
  55.     
  56.     theErr = FSRead ( fileRef, bytesRead, theLine );
  57.     if ( (theErr != noErr) && (theErr != eofErr) )
  58.     {
  59.         theLine[nil] = nil;
  60.         goto EXIT_FUNCTION;
  61.     }
  62.     
  63.     /* make sure the string is terminated */
  64.     theLine[lineSize] = nil;
  65.     
  66.     
  67.     EXIT_FUNCTION:
  68.     
  69.     return (theErr == eofErr)? noErr : theErr;
  70. } /* FileReadBytes */
  71.  
  72.  
  73. /* Finder alias handling */
  74. #pragma mark -
  75.  
  76. /* From Apple Developer Support: New Technical Notes;
  77.     "FL 29/30? Resolving Alias File Quietly"
  78.     Set the last Boolean (mountRemoteVols) to true to avoid the resolving of
  79.     aliases that map to unmounted volumes. You definitly want to do that
  80.     because you don't want the user interface for mounting remote volumes
  81.     coming up on servers when there's no one around to deal with that interface. */
  82. pascal OSErr
  83. ResolveAliasFileMountOption ( FSSpec *fileFSSpec, Boolean resolveAliasChains,
  84.     Boolean *targetIsFolder, Boolean *wasAliased, Boolean mountRemoteVols )
  85. {
  86.     /* maximum number of aliases to resolve before giving up */
  87.     #define MAXCHAINS 10
  88.     
  89.     short        myResRefNum;
  90.     Handle        alisHandle;
  91.     FSSpec        initFSSpec;
  92.     Boolean        updateFlag;
  93.     Boolean        foundFlag;
  94.     Boolean        wasAliasedTemp;
  95.     Boolean        specChangedFlag;
  96.     short        chainCount;
  97.     OSErr        retCode;
  98.     
  99.     if ( (fileFSSpec == NULL) || (targetIsFolder == nil) || (wasAliased == nil) )
  100.     {
  101.         return paramErr;
  102.     }
  103.     
  104.     initFSSpec  = *fileFSSpec;    /* so FSSpec can be restored in case of error */
  105.     chainCount  = MAXCHAINS;    /* circular alias chain protection */
  106.     myResRefNum    = -1;            /* resource file not open */
  107.     
  108.     *targetIsFolder = foundFlag = specChangedFlag = false;
  109.     
  110.     /* loop through chain of alias files */
  111.     do
  112.     {
  113.         chainCount--;
  114.         
  115.         /* check if FSSpec is an alias file or a directory.
  116.             note that targetIsFolder => NOT wasAliased */
  117.         retCode = IsAliasFile ( fileFSSpec, wasAliased, targetIsFolder );
  118.         if ( (retCode != noErr) || !(*wasAliased) )
  119.         {
  120.             break;
  121.         }
  122.         
  123.         /* get the resource file reference number */
  124.         myResRefNum    = FSpOpenResFile ( fileFSSpec, fsCurPerm );
  125.         retCode        = ResError ();
  126.         if ( myResRefNum == -1 )
  127.         {
  128.             break;
  129.         }
  130.         
  131.         /* the first 'alis' resource in the file is the appropriate alias */
  132.         alisHandle = Get1IndResource ( rAliasType, 1 );
  133.         retCode    = ResError ();
  134.         if ( alisHandle == nil )
  135.         {
  136.             break;
  137.         }
  138.         
  139.         /* load the resource explicitly in case SetResLoad(FALSE) */
  140.         LoadResource ( alisHandle );
  141.         retCode = ResError ();
  142.         if ( retCode != noErr )
  143.         {
  144.             break;
  145.         }
  146.         
  147.         retCode = FollowFinderAlias ( fileFSSpec, (AliasHandle)alisHandle, mountRemoteVols, fileFSSpec, &updateFlag );
  148.         
  149.         /* FollowFinderAlias returns nsvErr if volume not mounted */
  150.         if ( retCode == noErr )
  151.         {
  152.             if ( updateFlag )
  153.             {
  154.                 /* the resource in the alias file needs updating */
  155.                 ChangedResource    ( alisHandle );
  156.                 WriteResource    ( alisHandle );
  157.             }
  158.             
  159.             specChangedFlag    = true; /* in case of error, restore file spec */
  160.             retCode = IsAliasFile ( fileFSSpec, &wasAliasedTemp, targetIsFolder );
  161.             if ( retCode == noErr )
  162.             {
  163.                 /* we're done unless it was an alias file and we're following a chain */
  164.                 foundFlag = !(wasAliasedTemp && resolveAliasChains);
  165.             }
  166.         }
  167.         
  168.         CloseResFile( myResRefNum );
  169.         myResRefNum = -1;
  170.     } while ( (retCode == noErr) && (chainCount > nil) && !(foundFlag) );
  171.     
  172.     /* return file not found error for circular alias chains */
  173.     if ( (chainCount == nil) && !(foundFlag) )
  174.     {
  175.         retCode = fnfErr;
  176.     }
  177.     
  178.     /* if error occurred, close resource file and restore the original FSSpec */
  179.     if ( myResRefNum != -1 )
  180.     {
  181.         CloseResFile ( myResRefNum );
  182.     }
  183.     
  184.     if ( (retCode != noErr) && specChangedFlag )
  185.     {
  186.         *fileFSSpec = initFSSpec;
  187.     }
  188.     
  189.     return retCode;
  190. } /* ResolveAliasFileMountOption */
  191.  
  192.  
  193. /* sets aliasFileFlag if the FSSpec points to an alias file;
  194.     sets folderFlag if the FSSpec points to a folder */
  195. pascal OSErr
  196. IsAliasFile ( const FSSpec *fileFSSpec, Boolean *aliasFileFlag, Boolean *folderFlag )
  197. {
  198.     CInfoPBRec    myCInfoPBRec;
  199.     OSErr        retCode;
  200.     
  201.     if ( (fileFSSpec == NULL) || (aliasFileFlag == nil) || (folderFlag == nil) )
  202.     {
  203.         return paramErr;
  204.     }
  205.     
  206.     *aliasFileFlag = *folderFlag = false;
  207.     
  208.     /* get the item's catalog information */
  209.     myCInfoPBRec.hFileInfo.ioCompletion    = NULL;
  210.     myCInfoPBRec.hFileInfo.ioNamePtr    = (StringPtr)(fileFSSpec->name);
  211.     myCInfoPBRec.hFileInfo.ioVRefNum    = fileFSSpec->vRefNum;
  212.     myCInfoPBRec.hFileInfo.ioDirID        = fileFSSpec->parID;
  213.     myCInfoPBRec.hFileInfo.ioFVersNum    = nil;
  214.     /* MFS compatibility, see TN #204 */
  215.     myCInfoPBRec.hFileInfo.ioFDirIndex    = nil;
  216.     
  217.     retCode = PBGetCatInfoSync ( &myCInfoPBRec );
  218.     
  219.     /* set aliasFileFlag if the item is not a directory and the aliasFile bit is set */
  220.     if ( retCode == noErr )
  221.     {
  222.         /* check directory bit */
  223.         if ( (myCInfoPBRec.hFileInfo.ioFlAttrib & ioDirMask) != nil )
  224.         {
  225.             *folderFlag = true;
  226.         }
  227.         /* check isAlias bit */
  228.         else if ( (myCInfoPBRec.hFileInfo.ioFlFndrInfo.fdFlags & 0x8000) != nil )
  229.         {
  230.             *aliasFileFlag = true;
  231.         }
  232.     }
  233.     
  234.     return retCode;
  235. } /* IsAliasFile */
  236.  
  237.  
  238. /* this is included in the newer header files, so has been removed */
  239. #if 0
  240. /* FollowFinderAlias resolves an alias taken from a Finder alias file,
  241.     updating the alias record (but not the alias resource in the file) if necessary.
  242.     Warning: This trap is used internally by Apple Computer, Inc.
  243.     It has not been tested for use by application software.
  244.     While we do not anticipate any problems, it is the responsibility of the developer
  245.     to ensure that it operates appropriately and reliably for their application. */
  246. pascal OSErr
  247. FollowFinderAlias ( const FSSpec *fromFile, AliasHandle alias, Boolean logon, FSSpec *target, Boolean *wasChanged )
  248. = {0x700F, 0xA823}; /* MOVEQ #$0F,D0; _AliasDispatch; */
  249. #endif /* 0 */
  250.  
  251.  
  252. /*****  EOF  *****/
  253.